#pragma once

#include "Camera.h"
#include "GrassPatch.h"

extern Camera cam;
extern float lod;
extern float lodDecay;

Point3D getRandomPointOnTriangle(Point3D p1, Point3D p2, Point3D p3) {
	//Barycentric Coordinates
	float s = rand()/(float)RAND_MAX;
	float r = rand()/(float)RAND_MAX;
	if (s + r > 1) {
		s = 1 - s;
		r = 1 - r;
	}

	Point3D out;
	out.x = p1.x + ((p2.x - p1.x)*s) + ((p3.x - p1.x)*r);
	out.y = p1.y + ((p2.y - p1.y)*s) + ((p3.y - p1.y)*r);
	out.z = p1.z + ((p2.z - p1.z)*s) + ((p3.z - p1.z)*r);
	
	return out;
}

GrassPatch :: GrassPatch(Point3D points[4], int numOfBlades, float size, Vector3 normals[4])
{
	copy(normals, normals+4, this->normals);
	copy(points, points+4, this->points);

	
	for (int i = 0; i < numOfBlades/2; i++)
	{
		//Add grass to first triangle
		GrassBlade* grassBlade = new GrassBlade();
		Point3D pos = getRandomPointOnTriangle(points[0], points[1], points[2]);
		grassBlade->setNormal(normals[0]);
		grassBlade->setSize(size);
		grassBlade->setPosition(pos);
		blades.push_back(grassBlade);

		//Add grass to second triangle
		grassBlade = new GrassBlade();
		pos = getRandomPointOnTriangle(points[0], points[2], points[3]);
		grassBlade->setNormal(normals[0]);
		grassBlade->setSize(size);
		grassBlade->setPosition(pos);
		blades.push_back(grassBlade);
	}
}

void GrassPatch :: setGroundColorMaterial()
{
	GLfloat mat_ambient[] = {0.0f, 0.2f, 0.0f, 1.0f};
	GLfloat mat_diffuse[] = {0.0f, 0.8f, 0.0f, 1.0f};
	GLfloat mat_specular[] = {0.0f, 0.0f, 0.0f, 0.0f};
	GLfloat mat_shininess[] = {0.0f};
	glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
	glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
	glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
}

float GrassPatch :: distanceToCamera()
{
	float distance = 0;

	float xDist = cam.pos.getX() - position.x;
	float yDist = cam.pos.getY() - position.y;
	float zDist = cam.pos.getZ() - position.z;

	distance = sqrt((xDist * xDist) + (yDist * yDist) + (zDist * zDist));

	return distance;
}

void GrassPatch :: draw()
{
	glPushMatrix();

	setGroundColorMaterial();

	glBegin(GL_POLYGON);
		glNormal3f(normals[0].getX(), normals[0].getY(), normals[0].getZ());
		glVertex3f(points[0].x, points[0].y, points[0].z);
		glNormal3f(normals[1].getX(), normals[1].getY(), normals[1].getZ());
		glVertex3f(points[1].x, points[1].y, points[1].z);
		glNormal3f(normals[2].getX(), normals[2].getY(), normals[2].getZ());
		glVertex3f(points[2].x, points[2].y, points[2].z);
	glEnd();

	glBegin(GL_POLYGON);
		glNormal3f(normals[0].getX(), normals[0].getY(), normals[0].getZ());
		glVertex3f(points[0].x, points[0].y, points[0].z);
		glNormal3f(normals[2].getX(), normals[2].getY(), normals[2].getZ());
		glVertex3f(points[2].x, points[2].y, points[2].z);
		glNormal3f(normals[3].getX(), normals[3].getY(), normals[3].getZ());
		glVertex3f(points[3].x, points[3].y, points[3].z);
	glEnd();

	float distance = distanceToCamera();

	int numToDraw = blades.size();
	if (distance < lod+lodDecay) {
		numToDraw = blades.size();
		if (distance > lod) {
			numToDraw *= (lod+lodDecay-distance)/lodDecay;
		}
		for (int i = 0; i < numToDraw; i++)
		{
			blades[i]->draw();
		}
	}

	glPopMatrix();
}

void GrassPatch :: update(float delta)
{
	for (unsigned int i = 0; i < blades.size(); i++)
	{
		blades[i]->update(delta);
	}
}

